#ifndef XGE_GRAPHICS_ANIM_TEXTURE_H_
#define XGE_GRAPHICS_ANIM_TEXTURE_H_
#include "xge_common_config.h"
#include "anim.h"
#include "g_texture.h"
#include "xallocator.h"

namespace xge{
namespace graphics{
  // This class allows us to implement the original texture
  // animation in 2D game .It basically have 2 function .
  class AnimTexture : public Animator , public Allocator {
  public:
    virtual void Action( BaseNode* node , const Timer::tick_t& diff_time );
    enum {
      MODE_FORWARD = 0 , // the animation will forwarding play
      MODE_BACKWARD= 1 , // the animation will backward play
      MODE_LOOP    = 2 , // the animation will loop
      MODE_NOLOOP  = 4  // the animation will play only once
    };
  public:
    // Ctor of this animation texture
    AnimTexture( const TexturePtr& tex_ptr , const Rect& texture_rect ,
      float f_width , float f_height , size_t frames , size_t fps , int mode = MODE_LOOP | MODE_FORWARD )
      :mode_(mode),texture_(tex_ptr),frame_position_(0),texture_rect_(texture_rect),time_diff_(0),pause_(false){
        BuildParamter(texture_rect,f_width,f_height,frames,fps);
    }
    AnimTexture( const Rect& texture_rect ,
      float f_width , float f_height , size_t frames , size_t fps , int mode = MODE_LOOP | MODE_FORWARD )
    :mode_(mode),frame_position_(0),texture_rect_(texture_rect),time_diff_(0),pause_(false){
      BuildParamter(texture_rect,f_width,f_height,frames,fps);
    }
  public:
    // interface for controlling the anim_texture
    // this will make the whole ani_texture return to
    // the first frame of the animation !
    void Reset () {
      frame_position_ =0;
      time_diff_ =0;
    }
    void Pause() {
      pause_ = true;
    }
    bool IsPause() const {
      return pause_;
    }
    void Resume() {
      pause_ = false;
    }
  public:
    // this will set the current frame to the targeting frame
    // and play the animation 
    void set_frame_position ( size_t index ) {
      if( index> frames() )
        frame_position_ = frames();
      frame_position_ = index;
    }
    size_t frame_position() const {
      return frame_position_;
    }
    size_t frames() const {
      return frames_;
    }
    void set_frames( size_t f ) {
      if( f>row_num_*col_num_ ) {
        return;
      } else {
        frames_ = f ;
      }
    }
    // this will change the fps of this animation
    void set_fps( size_t fps ) {
      fps_ = 1000/fps;
    }
    size_t fps() const {
      return (size_t)(1000/fps_);
    }
    // this will change the texture of the animation texture 
    void set_texture( const TexturePtr& tex_ptr ) {
      texture_ = tex_ptr;
    }
    // this will change the texture of this animation 
    void set_texture_rect( const Rect& rect ) {
      texture_rect_ = rect;
      col_num_ = (size_t)(rect.height()/frame_height_);
      row_num_ = (size_t)(rect.width() / frame_width_);
      if( frames_ > col_num_*row_num_ )
        frames_ = col_num_*row_num_;
    }
    void set_frame( float width , float height ) {
      col_num_ = (size_t)(texture_rect().height()/height);
      row_num_ = (size_t)(texture_rect().width() / width);
      if( frames_ > col_num_*row_num_ )
        frames_ = col_num_*row_num_;
      frame_width_ = width;
      frame_height_ = height;
    }
    // texture of this animation  
    const TexturePtr& texture() const {
      return texture_;
    }
    const Rect& texture_rect() const{
      return texture_rect_;
    }
  public:
    void set_mode( int mode ) {
      mode_ |= mode;
    }
    bool forward() const {
      static const size_t kMask = 1;
      return static_cast<bool>( (mode_ & kMask) ==0);
    }
    bool loop () const {
      static const size_t kMask = 2;
      return static_cast<bool>( (mode_ & kMask ) ==0);
    }
    bool over() const {
      return loop() ? false : 
        (forward() ? frame_position() == frames()+1 : frame_position() == 0);
    }
  private:
    // building the parameter of this Animation .
    void BuildParamter( const Rect& texture_rect ,
      float f_width , float f_height , size_t frames , size_t fps ) {
        frames_ = frames;
        frame_width_ = f_width;
        frame_height_= f_height;
        set_texture_rect(texture_rect_);
        fps_ = 1000/fps;
    }

  private:
    int mode_;
    size_t target_frame;
    size_t fps_, frames_ ,frame_position_ ;
    Rect texture_rect_ ;
    TexturePtr texture_;
    size_t col_num_ , row_num_ ;
    float frame_width_ , frame_height_;
    Timer::tick_t time_diff_;
    bool pause_;
  };


}// namespace graphics
}// namespace xge

#endif// XGE_GRAPHICS_ANIM_TEXTURE_H_